﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using Microsoft.Phone.Controls;
using Polenter.Serialization;

namespace Achievements
{
    public class Achievement : INotifyPropertyChanged
    {
        public const string SmallImageUriPropertyString = "SmallImageUri";
        public const string LargeImageUriPropertyString = "LargeImageUri";
        public const string SmallImagePathPropertyString = "SmallImagePath";
        public const string LargeImagePathPropertyString = "LargeImagePath";
        public const string TitlePropertyString = "Title";
        public const string DescriptionPropertyString = "Description";
        public const string IsHiddenPropertyString = "IsHidden";
        public const string IsUnlockedPropertyString = "IsUnlocked";
        public const string AchievementValuePropertyString = "AchievementValue";

        private int _achievementValue;
        private string _description;
        private bool _isHidden;
        private bool _isUnlocked;
        private string _largeImagePath;
        private string _smallImagePath;
        private string _title;

        /// <summary>
        /// Gets or sets the achievement value.
        /// </summary>
        /// <value>
        /// The achievement value.
        /// </value>
        public int AchievementValue
        {
            get { return _achievementValue; }
            set
            {
                if (_achievementValue != value)
                {
                    _achievementValue = value;
                    RaisePropertyChanged(AchievementValuePropertyString);
                }
            }
        }

        /// <summary>
        /// Gets or sets the Image path for the small image. The SmallImageUri will use this path, with the UriKind 'RelativeOrAbsolute'
        /// </summary>
        /// <value>
        /// The small image path.
        /// </value>
        public string SmallImagePath
        {
            get { return _smallImagePath; }
            set
            {
                if (_smallImagePath != value)
                {
                    _smallImagePath = value;
                    RaisePropertyChanged(SmallImagePathPropertyString);
                    RaisePropertyChanged(SmallImageUriPropertyString);
                }
            }
        }

        /// <summary>
        /// Gets the small image URI.
        /// </summary>
        [ExcludeFromSerialization]
        public Uri SmallImageUri
        {
            get { return new Uri(SmallImagePath, UriKind.RelativeOrAbsolute); }
        }

        /// <summary>
        /// Gets or sets the Image path for the large image. The LargeImageUri will use this path, with the UriKind 'RelativeOrAbsolute'
        /// </summary>
        /// <value>
        /// The large image path.
        /// </value>
        public string LargeImagePath
        {
            get { return _largeImagePath; }
            set
            {
                if (_largeImagePath != value)
                {
                    _largeImagePath = value;
                    RaisePropertyChanged(LargeImagePathPropertyString);
                    RaisePropertyChanged(LargeImageUriPropertyString);
                }
            }
        }

        /// <summary>
        /// Gets the large image URI.
        /// </summary>
        [ExcludeFromSerialization]
        public Uri LargeImageUri
        {
            get { return new Uri(LargeImagePath, UriKind.RelativeOrAbsolute); }
        }

        /// <summary>
        /// Gets or sets the title.
        /// </summary>
        /// <value>
        /// The title.
        /// </value>
        public string Title
        {
            get { return _title; }
            set
            {
                if (_title != value)
                {
                    _title = value;
                    RaisePropertyChanged(TitlePropertyString);
                }
            }
        }

        /// <summary>
        /// Gets or sets the description.
        /// </summary>
        /// <value>
        /// The description.
        /// </value>
        public string Description
        {
            get { return _description; }
            set
            {
                if (_description != value)
                {
                    _description = value;
                    RaisePropertyChanged(DescriptionPropertyString);
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is hidden.
        /// </summary>
        /// <value>
        ///   <c>true</c> if this instance is hidden; otherwise, <c>false</c>.
        /// </value>
        public bool IsHidden
        {
            get { return _isHidden; }
            set
            {
                if (_isHidden != value)
                {
                    _isHidden = value;
                    RaisePropertyChanged(IsHiddenPropertyString);
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is unlocked.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is unlocked; otherwise, <c>false</c>.
        /// </value>
        public bool IsUnlocked
        {
            get { return _isUnlocked; }
            set
            {
                if (_isUnlocked != value)
                {
                    _isUnlocked = value;
                    RaisePropertyChanged(IsUnlockedPropertyString);
                }
            }
        }

        /// <summary>
        /// Unlocks the achievement.
        /// </summary>
        protected void UnlockAchievement()
        {
            IsUnlocked = true;
            RaiseAchievementUnlocked(this);
        }


        /// <summary>
        /// Alerts the UI that the achievement has been unlocked. Displays the popup on the screen.
        /// </summary>
        /// <param name="achievement">The achievement.</param>
        public static void RaiseAchievementUnlocked(Achievement achievement)
        {
            var aPopup = new AchievementPopup {Achievement = achievement};

            var pop = new Popup {Child = aPopup, IsOpen = true};


            var frame = Application.Current.RootVisual as PhoneApplicationFrame;
            if (frame != null)
            {
                var page = frame.Content as PhoneApplicationPage;
                if (page != null)
                {
                    UIElement content = page.Content;
                    var grid = content as Grid;
                    if (grid != null)
                    {
                        grid.Children.Add(pop);
                    }
                    else
                    {
                        var panel = content as Panel;
                        if (panel != null)
                        {
                            panel.Children.Add(pop);
                        }
                    }
                    //could not attach to parent.
                    //sizing may be inconsistent now.
                }
            }
        }

        /// <summary>
        /// Raises the property changed event.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        public void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region Implementation of INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}